<template>
  <div class="flex flex-col items-center justify-center h-screen bg-gray-100">
    <div class="mb-4">
      <button
          v-if="!isCalling && !isInCall"
          @click="startCall"
          class="px-4 py-2 bg-blue-500 text-white rounded"
      >
        开始音视频通话
      </button>
      <div v-else-if="isCalling && !isInCall">
        <button
            @click="acceptCall"
            class="px-4 py-2 bg-green-500 text-white rounded mr-2"
        >
          接受
        </button>
        <button
            @click="rejectCall"
            class="px-4 py-2 bg-red-500 text-white rounded"
        >
          拒绝
        </button>
      </div>
    </div>

    <div class="flex space-x-4">
      <div>
        <h3 class="text-center text-lg">本地视频</h3>
        <video ref="localVideo" class="w-64 h-48 bg-gray-300" autoplay playsinline></video>
      </div>
      <div v-if="isInCall">
        <h3 class="text-center text-lg">远程视频</h3>
        <video ref="remoteVideo" class="w-64 h-48 bg-gray-300" autoplay playsinline></video>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue';
import { io } from 'socket.io-client';

// 连接服务器
const socket = io('http://localhost:8560');

// WebRTC 相关变量
let localStream;
let peerConnection;

// Vue refs
const localVideo = ref(null);
const remoteVideo = ref(null);

// Vue reactive state
const state = reactive({
  isCalling: false,
  isInCall: false,
});

// 配置 STUN 服务器
const configuration = {
  iceServers: [
    {
      urls: 'stun:stun.l.google.com:19302',
    },
  ],
};

// 获取用户音视频
async function getMedia() {
  try {
    localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
    localVideo.value.srcObject = localStream;
  } catch (error) {
    console.error('获取本地音视频流失败:', error);
  }
}

// 初始化 WebRTC 连接
function createPeerConnection() {
  if (!localStream) {
    console.error('本地流未定义');
    return;
  }

  peerConnection = new RTCPeerConnection(configuration);

  // 处理 ICE 候选者
  peerConnection.onicecandidate = ({ candidate }) => {
    if (candidate) {
      socket.emit('ice-candidate', candidate);
    }
  };

  // 添加本地音视频流到 PeerConnection
  localStream.getTracks().forEach(track => {
    peerConnection.addTrack(track, localStream);
  });

  // 处理对方的音视频流
  peerConnection.ontrack = (event) => {
    remoteVideo.value.srcObject = event.streams[0];
  };
}

// 处理信令消息
socket.on('offer', async (offer) => {
  if (!peerConnection) {
    await getMedia();
    createPeerConnection();
  }
  state.isCalling = true;
  await peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
});

socket.on('answer', async (answer) => {
  if (peerConnection) {
    await peerConnection.setRemoteDescription(new RTCSessionDescription(answer));
    state.isInCall = true;
  }
});

socket.on('ice-candidate', async (candidate) => {
  if (candidate && peerConnection.remoteDescription) {
    try {
      await peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
    } catch (error) {
      console.error('添加 ICE 候选者失败:', error);
    }
  }
});

// 开始音视频通话
async function startCall() {
  await getMedia();
  createPeerConnection();
  const offer = await peerConnection.createOffer();
  await peerConnection.setLocalDescription(offer);
  socket.emit('offer', offer);
  state.isCalling = true;
}

// 接受通话
async function acceptCall() {
  state.isCalling = false;
  state.isInCall = true;
  if (!peerConnection) {
    await getMedia();
    createPeerConnection();
  }
  const answer = await peerConnection.createAnswer();
  await peerConnection.setLocalDescription(answer);
  socket.emit('answer', answer);
}

// 拒绝通话
function rejectCall() {
  state.isCalling = false;
  if (peerConnection) {
    peerConnection.close();
    peerConnection = null;
  }
  socket.emit('reject-call');
}
</script>
